package safety

import (
	"context"
	"fmt"
	"gitee.com/bobo-rs/idea-space-framework/consts"
	"gitee.com/bobo-rs/idea-space-framework/enums"
	"gitee.com/bobo-rs/idea-space-framework/pkg/sredis"
	"gitee.com/bobo-rs/idea-space-framework/pkg/utils"
	"time"
)

const (
	secretTagMacExpire = time.Minute * 10 // 效期十分钟
	macSep             = `-`              // Mac分割符
)

// SetSecretTagMac 设置同一个Tag且同一个用户Mac安全密钥缓存
func (s *sSafety) SetSecretTagMac(ctx context.Context, tag enums.SafeTags, secret string) error {
	// 获取key
	key, err := s.GetTagMacKey(ctx, tag)
	if err != nil {
		return err
	}
	// 设置密钥
	return sredis.NewCache().Set(ctx, key, secret, secretTagMacExpire)
}

// GetSecretTagMac 获取同一个Tag且同一个用户Mac安全密钥
func (s *sSafety) GetSecretTagMac(ctx context.Context, tag enums.SafeTags) (*string, error) {
	// 获取key
	key, err := s.GetTagMacKey(ctx, tag)
	if err != nil {
		return nil, err
	}

	// 获取密钥
	r, err := sredis.NewCache().Get(ctx, key)
	if err != nil {
		return nil, err
	}
	// 读取密钥
	secret := r.String()
	if len(secret) == 0 {
		return nil, fmt.Errorf(`%s密钥已过期,%s`, tag, *key)
	}
	return &secret, nil
}

// RemoveSecretTagMac 销毁同一个Tag且同一个用户Mac安全密钥
func (s *sSafety) RemoveSecretTagMac(ctx context.Context, tag enums.SafeTags) error {
	// 删除密钥
	key, err := s.GetTagMacKey(ctx, tag)
	if err != nil {
		return err
	}
	_, err = sredis.NewCache().Remove(ctx, key)
	return err
}

// SetSecret1MinuteTagMacRefreshNum 设置同一个Tag同一个用户Mac1分钟刷新安全密钥次数
func (s *sSafety) SetSecret1MinuteTagMacRefreshNum(ctx context.Context, tag enums.SafeTags) error {
	// 获取KEY
	key, err := s.Get1MinuteTagMacKey(ctx, tag)
	if err != nil {
		return err
	}
	// 获取刷新数量
	num, err := s.GetSecret1MinuteTagMacRefreshNum(ctx, tag)
	if err != nil {
		return err
	}
	num += 1
	// 缓存一分钟
	return sredis.NewCache().Set(ctx, key, num, time.Minute)
}

// GetSecret1MinuteTagMacRefreshNum 获取同一个Tag同一个用户Mac1分钟刷新安全密钥次数
func (s *sSafety) GetSecret1MinuteTagMacRefreshNum(ctx context.Context, tag enums.SafeTags) (int, error) {
	// 获取KEY
	key, err := s.Get1MinuteTagMacKey(ctx, tag)
	if err != nil {
		return 0, err
	}
	// 获取刷新数量
	r, err := sredis.NewCache().Get(ctx, key)
	if err != nil {
		return 0, err
	}
	return r.Int(), nil
}

// SetSecret1HourTagMacRefreshNum 设置同一个Tag和用户Mac1小时内刷新密钥次数
func (s *sSafety) SetSecret1HourTagMacRefreshNum(ctx context.Context, tag enums.SafeTags) error {
	// 获取已缓存数量
	num, err := s.GetSecret1HourTagMacRefreshNum(ctx, tag)
	if err != nil {
		return err
	}
	// 获取KEY
	key, err := s.Get1HourTagMacKey(ctx, tag)
	if err != nil {
		return err
	}

	// 缓存一小时
	return sredis.NewCache().Set(ctx, key, num+1, time.Hour)
}

// GetSecret1HourTagMacRefreshNum 获取同一个Tag和用户Mac1小时内刷新密钥次数
func (s *sSafety) GetSecret1HourTagMacRefreshNum(ctx context.Context, tag enums.SafeTags) (int, error) {
	// 获取KEY
	key, err := s.Get1HourTagMacKey(ctx, tag)
	if err != nil {
		return 0, err
	}
	// 获取刷新数量
	r, err := sredis.NewCache().Get(ctx, key)
	if err != nil {
		return 0, err
	}
	return r.Int(), nil
}

// SetSecret1MinuteTagRefreshNum 设置同一个Tag1分钟密钥刷新次数
func (s *sSafety) SetSecret1MinuteTagRefreshNum(ctx context.Context, tag enums.SafeTags) error {
	// 获取刷新次数
	num, err := s.GetSecret1MinuteTagRefreshNum(ctx, tag)
	if err != nil {
		return err
	}

	// 设置刷新数量，缓存一分钟
	return sredis.NewCache().Set(
		ctx, utils.SafeSecretCacheKey(consts.SafeSecret1MinuteTag, string(tag)), num+1, time.Minute,
	)
}

// GetSecret1MinuteTagRefreshNum 获取同一个Tag1分钟密钥刷新次数
func (s *sSafety) GetSecret1MinuteTagRefreshNum(ctx context.Context, tag enums.SafeTags) (int, error) {
	// 获取刷新数量
	r, err := sredis.NewCache().Get(
		ctx, utils.SafeSecretCacheKey(consts.SafeSecret1MinuteTag, string(tag)),
	)
	if err != nil {
		return 0, err
	}
	return r.Int(), nil
}

// SetSecret24HourTagRefreshNum 设置同一个Tag24小时内密钥刷新次数
func (s *sSafety) SetSecret24HourTagRefreshNum(ctx context.Context, tag enums.SafeTags) error {
	// 获取刷新数量
	num, err := s.GetSecret24HourTagRefreshNum(ctx, tag)
	if err != nil {
		return err
	}
	now := time.Now()
	// 计算明天的日期
	tomorrow := now.AddDate(0, 0, 1) // 0年，0月，1天
	// 将时间设置为凌晨0点0分0秒
	midnight := time.Date(tomorrow.Year(), tomorrow.Month(), tomorrow.Day(), 0, 0, 0, 0, time.Local)

	// 缓存时间到明日凌晨零点，并把今明两日时间秒戳转为分钟
	expire := time.Minute * (time.Duration(midnight.Unix()-now.Unix()) / 60)

	// 设置刷新数量
	return sredis.NewCache().Set(
		ctx, utils.SafeSecretCacheKey(consts.SafeSecret24HourTag, string(tag)), num+1, expire,
	)
}

// GetSecret24HourTagRefreshNum 获取同一个Tag24小时内密钥刷新次数
func (s *sSafety) GetSecret24HourTagRefreshNum(ctx context.Context, tag enums.SafeTags) (int, error) {
	// 获取刷新次数
	r, err := sredis.NewCache().Get(
		ctx, utils.SafeSecretCacheKey(consts.SafeSecret24HourTag, string(tag)),
	)
	if err != nil {
		return 0, err
	}
	return r.Int(), nil
}

// GetTagMacKey 获取安全密钥缓存KEY
func (s *sSafety) GetTagMacKey(ctx context.Context, tag enums.SafeTags) (*string, error) {
	// 设置key
	key := utils.SafeSecretCacheKey(consts.SafeSecretTagIp, string(tag), utils.GetIp(ctx))
	return &key, nil
}

// Get1MinuteTagMacKey 获取密钥1分钟内刷新密钥次数KEY
func (s *sSafety) Get1MinuteTagMacKey(ctx context.Context, tag enums.SafeTags) (*string, error) {
	// 设置KEY
	key := utils.SafeSecretCacheKey(consts.SafeSecret1MinuteLockTagIp, string(tag), utils.GetIp(ctx))
	return &key, nil
}

// Get1HourTagMacKey 获取Tag同一个用户Mac一小时刷新密钥次数KEY
func (s *sSafety) Get1HourTagMacKey(ctx context.Context, tag enums.SafeTags) (*string, error) {
	// 设置KEY
	key := utils.SafeSecretCacheKey(consts.SafeSecret1HourLockTagIp, string(tag), utils.GetIp(ctx))
	return &key, nil
}
